package com.ant.collect.service.impl;

import com.ant.collect.mapper.IndustryInformationMapper;
import com.ant.collect.pojo.ExcelDataEntity;
import com.ant.collect.pojo.IndustryInformation;
import com.ant.collect.service.IExcelDataEntityService;
import com.ant.collect.service.IIndustryInformationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hzd
 * @since 2025-10-29
 */
@Service
public class IndustryInformationServiceImpl extends ServiceImpl<IndustryInformationMapper, IndustryInformation> implements IIndustryInformationService {

    @Override
    public List<IndustryInformation> listTree() {
        // 1. 查询所有符合条件的字典数据（也可分页，视需求而定）
//        List<IndustryInformation> dicList = baseMapper.selectList(new QueryWrapper<IndustryInformation>().eq("dic_value","A")); // 自定义方法：按类型查询
//        // 2. 筛选顶级节点（parentId = 0 或 null）
//        List<IndustryInformation> topNodes = dicList.stream()
//                .filter(dic -> dic.getDicType() == null || dic.getDicType() == 0)
//                .collect(Collectors.toList());
//
//        // 3. 为每个顶级节点递归设置子节点
//        for (IndustryInformation topNode : topNodes) {
//            setChildren(topNode, dicList);
//        }

        List<IndustryInformation> dicList = baseMapper.selectList(null); // 自定义方法：按类型查询
        IndustryInformation root = buildIndustryTree(dicList);
        System.out.println(root);
        return dicList;
    }

    /**
     * 递归为节点设置子节点
     * @param parentNode 父节点
     * @param allDics 所有字典数据（避免多次查询数据库）
     */
    private void setChildren(IndustryInformation parentNode, List<IndustryInformation> allDics) {
        // 筛选当前父节点的子节点（parentId = 父节点 id）
        List<IndustryInformation> children = allDics.stream()
                .filter(dic -> parentNode.getDicValue().equals(dic.getDicType()))
                .collect(Collectors.toList());

        // 若有子节点，继续递归设置子节点的子节点
        if (!children.isEmpty()) {
            parentNode.setChildren(children);
            for (IndustryInformation child : children) {
                setChildren(child, allDics); // 递归
            }
        }
    }


    /**
     * 构建行业树形结构
     * @param allIndustries 所有行业数据
     * @return 根节点（depth=1的节点）
     */
    private static IndustryInformation buildIndustryTree(List<IndustryInformation> allIndustries) {
        // 找到根节点（层级深度为1）
        IndustryInformation root = allIndustries.stream()
                .filter(ind -> ind.getDicType() == 1)
                .findFirst()
                .orElseThrow(() -> new RuntimeException("未找到根节点（depth=1）"));

        // 递归为根节点添加子节点
        buildChildren(root, allIndustries);
        return root;
    }

    /**
     * 递归为父节点添加子节点
     * @param parent 父节点
     * @param all 所有行业数据
     */
    private static void buildChildren(IndustryInformation parent, List<IndustryInformation> all) {
        int childDepth = parent.getDicType() + 1;  // 子节点的层级深度 = 父节点深度 + 1
        String parentCode = parent.getDicValue();    // 父节点的编码（用于匹配子节点前缀）

        // 筛选子节点：depth为childDepth，且编码以父节点编码为前缀
        List<IndustryInformation> children = all.stream()
                .filter(ind -> ind.getDicType() == childDepth
                        && ind.getDicValue().startsWith(parentCode))
                .collect(Collectors.toList());

        // 为父节点设置子节点
        parent.setChildren(children);

        // 递归为每个子节点添加它们的子节点
        for (IndustryInformation child : children) {
            buildChildren(child, all);
        }
    }

   // excelDataRepository
    @Autowired
   IExcelDataEntityService excelDataEntityService;

    @Override
    public void saveExcelData(MultipartFile file) throws IOException {
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);

        Map<String, String> dicValueToIdMap = new HashMap<>();

        for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }

            String dicValue = getCellValue(row.getCell(2));
            String dicName = getCellValue(row.getCell(1));
            String dicTypeStr = getCellValue(row.getCell(3));
            int level = Integer.parseInt(dicTypeStr) + 1;

            String parentId = "0";
            if (level > 1) {
                String parentDicValue = dicValue.substring(0, dicValue.length() - 1);
                parentId = dicValueToIdMap.get(parentDicValue);
            }

            ExcelDataEntity entity = new ExcelDataEntity();

           // Integer.valueOf(dicValue), dicName,Integer.valueOf(dicValue), parentId, level
            entity.setId(Integer.valueOf(dicValue));
            entity.setName(dicName);
            entity.setParentId(Integer.parseInt( parentId));
            entity.setCode(Integer.valueOf(dicValue));
            entity.setLevel(level);
            System.out.println(entity);
            excelDataEntityService.save(entity);
            dicValueToIdMap.put(dicValue, dicValue);
        }
    }

    private String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf((int) cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }




    public static void main(String[] args) {
        // 输入的保单字符串（实际使用时替换为目标字符串）
        String insuranceStr = "以公与道路交通安全违法行为和道路交通事故相联系的浮动比率0％\n" +
                "上司两网保险费合计(人民币大写)：壹仟贰佰玖拾伍元整(￥：1295.00元）其中救助基金(1.0％）￥：12.95元\n" +
                "种站\n" +
                "渠（保险期间自2025年11月8日0时0分起至2026年11月8日0时0分止\n" +
                "道投保险合同争议解决方式诉讼\n" +
                "联保\n" +
                "系确代整备质量2805千克纳税人识别号915101006331170498\n" +
                "本认收168.30元0.00\n" +
                "公当年应缴往年补缴元滞纳金";



        String insuranceStr2 = "船合计（人民币大写）：SA壹佰陆拾捌元叁角LI（￥：168.30元）。的\n" +
                "信税完税凭证号（减免税证明号）开具税务机关\n" +
                "息1、本条款适用于《机动车交通事故责任强制保险条款》;本保险单系一次性打印，涂改无效。2、尊敬的客户：自投保次日起，您可以\n" +
                "）通过本公司网页www.groupama-sdig.com或全天24小时服务热线(投诉热线)956001以及营业网点核实保单及理赔等信息。若对查询结果\n" +
                "或有异议，请及时联系本公司，联系电话956001。3、本保险车辆车主：成都蚂蚁物流有限公司4、本保单保险费为含税金额，其中不含税\n" +
                "附保险费1221.70元、增值税73.30元。\n" +
                "特别提示：除法律法规另有约定外，投保人拥有保险合同解除权，涉及（减）退保保费的，退还给投保人。\n" +
                "本保单投保人为：成都蚂蚁物流有限公司\n" +
                "保险费合计（人民币大写）：贰仟零伍拾肆元壹角柒分（￥：2054.17元）\n" +
                "保险期间2025年10月25日0时0分起至2026年10月25日0时0分止\n" +
                "1、尊敬的客户：自投保次日起，您可以通过本公司网页www.groupama-sdig.com或全天24小时服务热线(投诉热线)956001以及营业网点核实保单及理赔等信息";

        // 提取所有目标大写金额（壹仟贰佰玖拾伍元整、贰仟零伍拾肆元壹角柒分）
        List<String> targetAmounts = extractInsuranceAmounts(insuranceStr2);

        try {
            BigDecimal number = chineseToNumber(targetAmounts.get(0));
            System.out.println(targetAmounts + " → " + number); // 输出：贰仟零伍拾肆元壹角柒分 → 2054.17
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        // 提取指定时间（2025年10月25日0时0分起至2026年10月25日0时0分止）
        String targetTime = extractInsurancePeriod(insuranceStr2);
        List<String> list = extractTimes(targetTime);
        System.out.println("list====>"+list);

        // 输出结果
        System.out.println("目标大写金额：" + (targetAmounts.isEmpty() ? "未找到匹配金额" : targetAmounts));
        System.out.println("指定保险期间：" + (targetTime != null ? targetTime : "未找到匹配时间"));
    }


    // 中文数字到阿拉伯数字的映射
    private static final Map<Character, Integer> NUM_MAP = new HashMap<>();
    // 中文单位到倍数的映射（元及以上的单位）
    private static final Map<Character, Long> UNIT_MAP = new HashMap<>();

    static {
        // 初始化数字映射
        NUM_MAP.put('零', 0);
        NUM_MAP.put('壹', 1);
        NUM_MAP.put('贰', 2);
        NUM_MAP.put('叁', 3);
        NUM_MAP.put('肆', 4);
        NUM_MAP.put('伍', 5);
        NUM_MAP.put('陆', 6);
        NUM_MAP.put('柒', 7);
        NUM_MAP.put('捌', 8);
        NUM_MAP.put('玖', 9);

        // 初始化单位映射（元及以上，按倍数从大到小排序）
        UNIT_MAP.put('亿', 100000000L);
        UNIT_MAP.put('万', 10000L);
        UNIT_MAP.put('仟', 1000L);
        UNIT_MAP.put('佰', 100L);
        UNIT_MAP.put('拾', 10L);
        UNIT_MAP.put('元', 1L); // 元作为整数部分的基准单位
    }

    /**
     * 将中文大写金额转换为数字金额（保留两位小数）
     * @param chineseAmount 中文大写金额（如“贰仟零伍拾肆元壹角柒分”）
     * @return 对应的数字金额（BigDecimal）
     * @throws IllegalArgumentException 输入格式错误时抛出
     */
    public static BigDecimal chineseToNumber(String chineseAmount) {
        if (chineseAmount == null || chineseAmount.trim().isEmpty()) {
            throw new IllegalArgumentException("输入金额不能为空");
        }
        String amount = chineseAmount.trim();

        // 分割“元”，区分整数部分（元之前）和小数部分（元之后，含角、分、整）
        String[] parts = amount.split("元");
        if (parts.length < 1) {
            throw new IllegalArgumentException("金额格式错误，缺少‘元’字");
        }
        String integerPartStr = parts[0]; // 整数部分（如“贰仟零伍拾肆”）
        String decimalPartStr = parts.length > 1 ? parts[1] : ""; // 小数部分（如“壹角柒分”“整”）

        // 解析整数部分（元前面的金额）
        long integerPart = parseIntegerPart(integerPartStr);
        // 解析小数部分（角、分）
        BigDecimal decimalPart = parseDecimalPart(decimalPartStr);

        // 组合整数和小数，保留两位小数
        return new BigDecimal(integerPart)
                .add(decimalPart)
                .setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 解析整数部分（元前面的中文数字，如“贰仟零伍拾肆”→2054）
     */
    private static long parseIntegerPart(String integerPartStr) {
        if (integerPartStr.isEmpty()) {
            return 0; // 如“元整”表示0元
        }

        long total = 0; // 总金额
        long current = 0; // 当前分段金额（用于处理“万”“亿”等大单位）
        int length = integerPartStr.length();

        for (int i = 0; i < length; i++) {
            char c = integerPartStr.charAt(i);

            if (NUM_MAP.containsKey(c)) {
                // 遇到数字（零-玖），判断下一位是否为单位（拾、佰、仟）
                int num = NUM_MAP.get(c);
                if (i + 1 < length && UNIT_MAP.containsKey(integerPartStr.charAt(i + 1))) {
                    // 下一位是单位（拾、佰、仟），当前数字×单位后加入current
                    char unitChar = integerPartStr.charAt(i + 1);
                    long unit = UNIT_MAP.get(unitChar);
                    current += num * unit;
                    i++; // 跳过已处理的单位
                } else {
                    // 下一位不是单位，直接加数字（通常是最后一位，如“伍”）
                    current += num;
                }
            } else if (UNIT_MAP.containsKey(c)) {
                // 遇到单位（拾、佰、仟、万、亿）
                long unit = UNIT_MAP.get(c);
                if (current == 0) {
                    // 单位前无数字（如“拾”表示10，“佰”表示100）
                    current = unit;
                } else {
                    // 单位前有数字（如“仟”→current×1000）
                    current *= unit;
                }
                // 遇到“万”或“亿”时，将current加入total并重置current（处理大单位分段）
                if (c == '万' || c == '亿') {
                    total += current;
                    current = 0;
                }
            } else if (c != '零') {
                // 非法字符（忽略“零”，其他字符报错）
                throw new IllegalArgumentException("无效字符：" + c);
            }
        }

        // 最后将剩余的current加入total（处理没有“万”“亿”的情况）
        total += current;
        return total;
    }

    /**
     * 解析小数部分（元后面的角、分，如“壹角柒分”→0.17，“整”→0.00）
     */
    private static BigDecimal parseDecimalPart(String decimalPartStr) {
        int jiao = 0; // 角
        int fen = 0;  // 分

        // 包含“整”表示无角分
        if (decimalPartStr.contains("整")) {
            return BigDecimal.ZERO;
        }

        // 提取“角”对应的数字
        if (decimalPartStr.contains("角")) {
            int jiaoIndex = decimalPartStr.indexOf("角");
            if (jiaoIndex > 0) {
                char jiaoChar = decimalPartStr.charAt(jiaoIndex - 1);
                jiao = NUM_MAP.getOrDefault(jiaoChar, 0);
            }
        }

        // 提取“分”对应的数字
        if (decimalPartStr.contains("分")) {
            int fenIndex = decimalPartStr.indexOf("分");
            if (fenIndex > 0) {
                char fenChar = decimalPartStr.charAt(fenIndex - 1);
                fen = NUM_MAP.getOrDefault(fenChar, 0);
            }
        }

        // 转换为小数（角=0.1，分=0.01）
        return new BigDecimal(jiao).multiply(new BigDecimal("0.1"))
                .add(new BigDecimal(fen).multiply(new BigDecimal("0.01")));
    }
    /**
     * 提取时间（格式：YYYY年MM月DD日HH时MM分）
     */
    private static List<String> extractTimes(String text) {
        List<String> result = new ArrayList<>();
        // 正则：匹配年份(4位)+月(1-2位)+日(1-2位)+时(1-2位)+分(1-2位)
        Pattern pattern = Pattern.compile("\\d{4}年(?:0?[1-9]|1[0-2])月(?:0?[1-9]|[12]\\d|3[01])日(?:[01]?\\d|2[0-3])时(?:[0-5]?\\d)分");
        Matcher matcher = pattern.matcher(text);

        while (matcher.find()) {
//            result.add(matcher.group());
            String time = convertToHyphenFormat(matcher.group());
            result.add(time);
        }

        return result;
    }
    /**
     * 将"YYYY年MM月DD日HH时MM分"格式转换为"YYYY-MM-DD"
     * @param input 输入的时间字符串
     * @return 转换后的日期字符串
     */
    public static String convertToHyphenFormat(String input) {
        // 正则表达式：匹配年、月、日（忽略后面的时间部分）
        // 分组1：年（4位数字），分组2：月（1-2位数字），分组3：日（1-2位数字）
        Pattern pattern = Pattern.compile("(\\d{4})年(\\d{1,2})月(\\d{1,2})日");
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            String year = matcher.group(1); // 提取年份（如"2025"）
            String month = matcher.group(2); // 提取月份（如"11"或"3"）
            String day = matcher.group(3); // 提取日期（如"3"或"15"）

            // 格式化月和日为两位数（不足两位补0），拼接为"YYYY-MM-DD"
            return String.format("%s-%02d-%02d",
                    year,
                    Integer.parseInt(month),
                    Integer.parseInt(day));
        } else {
            throw new IllegalArgumentException("输入格式不正确，应为'YYYY年MM月DD日HH时MM分'");
        }
    }
    /**
     * 提取所有符合格式的保险费大写金额
     * 支持两种格式：
     * - 保险费合计（人民币大写）：XXX
     * - 保险费合计(人民币大写)：XXX
     * @param input 输入字符串
     * @return 所有匹配的大写金额列表（空列表表示无匹配）
     */
    public static List<String> extractInsuranceAmounts(String input) {
        List<String> amounts = new ArrayList<>();
        if (input == null || input.trim().isEmpty()) {
            return amounts;
        }

        // 正则规则：
        // 匹配"保险费合计" + 全角或半角左括号 + "人民币大写" + 全角或半角右括号 + 冒号 + 中文金额（直到遇到左括号或换行）
        String regex = "保险费合计[\\(（]人民币大写[\\)）]：([\\u4e00-\\u9fa5]+?)[\\(（\\n]";
        // 编译正则（DOTALL模式支持换行匹配）
        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
        Matcher matcher = pattern.matcher(input);

        // 循环提取所有匹配项
        while (matcher.find()) {
            String amount = matcher.group(1).trim(); // 去除前后空格
            if (!amount.isEmpty()) {
                amounts.add(amount);
            }
        }
        return amounts;
    }

    /**
     * 提取保险期间时间（匹配"保险期间"后至"止"的内容）
     * @param input 输入字符串
     * @return 保险期间时间（null表示无匹配）
     */
    public static String extractInsurancePeriod(String input) {
        if (input == null || input.trim().isEmpty()) {
            return null;
        }

        // 正则规则：匹配"保险期间"后到"止"的所有内容（包含换行）
        String regex = "保险期间(.*?)止";
        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            return matcher.group(1).trim(); // 去除前后空格
        }
        return null;
    }
}
